package com.zeyi.blog.social.github;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黎先森
 */
public class GithubAuthFilter extends AbstractAuthenticationProcessingFilter {

    private static final String CLIENT_ID = "088d574da03e0c65c6ae";

    private static final String CLIENT_SECRET = "5cc6188dc695ab2db5ebaa382d1be232ca05dce9";

    private static final String TOKEN_URL = "https://github.com/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s";
    private static final String USER_INFO_URL = "https://api.github.com/user?access_token=%s";

    private RestTemplate restTemplate;

    public GithubAuthFilter(RestTemplate restTemplate) {
        super(new AntPathRequestMatcher("/auth/github", "GET"));
        this.restTemplate = restTemplate;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        //前端传来的code
        String code = request.getParameter("code");
        if (StringUtils.isBlank(code)) return null;

        //获取token
        String result = restTemplate.getForObject(
                String.format(TOKEN_URL, CLIENT_ID, CLIENT_SECRET, code),
                String.class
        );
        String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(result, "&");
        String accessToken = StringUtils.substringAfterLast(items[0], "=");

        //获取用户信息
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "token " + accessToken);
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(USER_INFO_URL, HttpMethod.GET, requestEntity, String.class);
        String userInfo = responseEntity.getBody();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        GithubUser githubUser = objectMapper.readValue(userInfo, GithubUser.class);

        GithubAuthToken githubAuthToken = new GithubAuthToken(githubUser);
        githubAuthToken.setDetails(authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(githubAuthToken);
    }
}
